/**
 * @filename:PpBomServiceImpl Sep 23, 2024
 * @project Wonder Vue Admin Api  1.1.0
 * Copyright(c) 2022 Wonder Co. Ltd. 
 * All right reserved. 
 */
package com.wonder.app.service.impl;

import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.app.domain.*;
import com.wonder.app.mapper.*;
import com.wonder.app.service.MaterialService;
import com.wonder.app.service.PpBomService;
import com.wonder.app.request.PpBomRequest;
import com.wonder.app.service.SfcOptrptService;
import com.wonder.app.service.TrayService;
import com.wonder.common.utils.DateUtils;
import com.wonder.common.utils.StringUtils;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.common.AjaxResult;

import java.util.*;
import java.util.stream.Collectors;

import com.wonder.constant.BillType;
import com.wonder.constant.IXqcConst;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.terracotta.quartz.TerracottaJobStore;
import org.web3j.abi.datatypes.primitive.Int;

import javax.swing.text.TabExpander;

/**
 * @Description:TODO(托盘)
 *
 * @version: 1.1.0
 * @author: Wonder
 *
 */
@Service
public class TrayServiceImpl  extends ServiceImpl<TrayDao, Tray> implements TrayService {


    @Autowired
    private TrayService trayService;
    @Autowired
    private TrayDao trayDao;
    @Autowired
    private PpBomService ppBomService;
    @Autowired
    private PpBomDao ppBomDao;

    @Autowired
    private MaterialService materialService;

    @Autowired
    private SfcOptrptService sfcOptrptService;

    @Autowired
    private SfcOptrptDao sfcOptrptDao;

    @Autowired
    private SfcproplanDetailDao sfcproplanDetailDao;

    @Autowired
    private SfcOptrptDetailDao sfcOptrptDetailDao;

    @Autowired
    private IVtuzxKingdeeService iVtuzxKingdeeService;

    /**
     * 验证托盘信息
     *
     * @param tray
     * @param type
     * @return String
     */
    @Override
    public String validate(Tray tray,String type){


        return "";
    }

    /**
     * 创建托盘信息
     * @param map
     * @return
     */
    public boolean createTray(Map<String, Object> map){
        int number = VtuzxUtil.getInt(map,"number");//几拖
        String proplanno =  VtuzxUtil.getString(map,"proplanno");//工序计划单号
        List<Map<String,Object>>  detailList = VtuzxUtil.getObject(map,"detail");//详细信息
        List<Tray> trayList = new ArrayList<>();//添加托盘的数据
        for (Map<String,Object> detailMap : detailList ){
            //构建单据
            Tray tray = new Tray();
            String BILLNO =  IXqcConst.createBillNo(BillType.TPTRAY);//托盘号
            tray.setFBILLNO(BILLNO);//托盘号
            tray.setITEMNUMBER(VtuzxUtil.getString(detailMap,"fmaterialnumber"));//件号
            tray.setFLOT(VtuzxUtil.getString(detailMap,"flot"));//批号
            tray.setFQTY(VtuzxUtil.getDouble(detailMap,"frealqty"));//托盘中物料数量
//            tray.setFOPERPNO(VtuzxUtil.getString(detailMap,"proplanno"));//工单号
            tray.setFMATERIALNUMBER(VtuzxUtil.getString(detailMap,"fmaterialnumber"));
            tray.setFMATERIALNAME(VtuzxUtil.getString(detailMap,"fmaterialname"));
            tray.setFUNITID(VtuzxUtil.getString(detailMap,"funitid"));
            tray.setFUNITNAME(VtuzxUtil.getString(detailMap,"funitname"));
            tray.setFSPECIFICATION(VtuzxUtil.getString(detailMap,"fspecification"));
            tray.setISPACKAGE(false);
            trayList.add(tray);
            //打印二维码


        }
        boolean result = trayService.saveOrUpdateBatch(trayList);
        return result;

    }

    /**
     * 获取托盘信息用于领料
     * @param map
     * @return
     * @throws Exception
     */
    public Map<String, Object> getTray(Map<String, Object> map) throws Exception{
        String billNo = map.get("billNo").toString();//托盘信息
        String moBillNo = VtuzxUtil.getString(map,"moBillNo");//生产订单号
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO,billNo));
        if (null == tray){
            throw new RuntimeException("该托盘信息不存在");
        }
        //查询是否是BOM中物料
        List<PpBom> ppBomList = ppBomDao.selectList(new LambdaQueryWrapper<PpBom>()
                .eq(PpBom::getFMOBILLNO,moBillNo));
//        if (null == ppBomList){
//            throw new Exception("当前领料托盘不为工单BOM中物料");
//        }
        List<String> fmaterialNoList = new ArrayList<>();
        //判断当前领的料是否是bom中的物料
        if(!VtuzxUtil.isEmpty(ppBomList)){
            for (PpBom ppBom : ppBomList){
                String fmaterialnumber = ppBom.getFMATERIALNUMBER();
                if (!fmaterialNoList.contains(fmaterialnumber)){
                    fmaterialNoList.add(fmaterialnumber);
                }
            }
        }
        String trayMaterialNo = tray.getFMATERIALNUMBER();//托盘中的物料信息
        if(fmaterialNoList.contains(trayMaterialNo)){
            tray.setIsPpBom(true);
        } else {
            tray.setIsPpBom(false);
        }
        Map<String,Object> data = new HashMap<>();
        data.put("data",tray);
        return data;
    }

    /**
     * 分批领料
     * @param map
     * @return
     * @throws Exception
     */
    public boolean updateTray(Map<String,Object> map) throws Exception {
        String billNo = map.get("fbillno").toString();//托盘号
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        Double yqty = tray.getFQTY();//托盘实际数量
        Double qty = VtuzxUtil.getDouble(map, "fqty");//领料数量
        Boolean res = false;
        if (yqty - qty == 0) {
            tray.setFQTY(yqty - qty);
            res =  trayService.updateById(tray);
        } else if (yqty - qty < 0) {
            throw new RuntimeException("领料数大于托盘数量，不允许领料");
        } else if (yqty - qty > 0) {
            tray.setFQTY(yqty - qty);
            //生成信二维码逻辑

            res =  trayService.updateById(tray);
        }


        return res;
    }

    /**
     * 增加托盘数量
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public boolean addTray(Map<String, Object> map,String type) throws Exception {
        String trayNo = VtuzxUtil.getString(map,"trayno");
        Double count = 0.0;
        if ("feed".equals(type)){
            count = VtuzxUtil.getDouble(map,"factualqty");//数量
        } else {
            count = VtuzxUtil.getDouble(map,"finfactqty");//数量
        }

        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, trayNo));
        Double trayQty = tray.getFQTY();//托盘实际数量
        tray.setFQTY(trayQty + count);
        boolean res =  trayService.updateById(tray);
        return res;
    }

    /**
     * 托盘列表手机端
     * @param map
     * @return
     */
    @Override
    public Map<String, Object> getTrayList(Map<String, Object> map) {
        int pageIndex = VtuzxUtil.getInt(map,"pageIndex");
        int pageSize = VtuzxUtil.getInt(map,"pageSize");
        String billNo = VtuzxUtil.getString(map,"billNo");//调拨单号
        List<Tray> dataList = trayDao.getTrayList(pageSize,pageIndex * pageSize,billNo);
        Map<String,Object> data = new HashMap<>();
        data.put("dataList",dataList);
        return data;
    }

    /**
     * 修改托盘数量
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public boolean updatetrayCount(Map<String, Object> map) throws Exception {
        String billNo = VtuzxUtil.getString(map,"fbillno");//托盘号
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        Double failCount = VtuzxUtil.getDouble(map,"failCount");//托盘号
        tray.setFQTY(tray.getFQTY() - failCount);
        tray.setUPDATETIME(new Date());
        boolean b = trayService.updateById(tray);
        return b;
    }

    /**
     * 创建托盘(手机端)
     * @param map
     * @param userName
     * @return
     * @throws Exception
     */
    @Override
    public String createTrayPda(Map<String, Object> map, String userName) throws Exception {
        String materialNo = VtuzxUtil.getString(map,"itemnumber");//物料编码
        String ironNo = VtuzxUtil.getString(map,"ironNo");//铁托号
        String flot = VtuzxUtil.getString(map,"flot");//批号
        //限制批号必录
        if (VtuzxUtil.isEmpty(flot)){
            throw new RuntimeException("批号必填");
        }
        String suffix = VtuzxUtil.getString(map,"suffix");//后缀
        String inStockTime = VtuzxUtil.getString(map,"inStockTime");//入库日期
        //根据编码查询名称等信息
        List<String> materialNoList = new ArrayList<>();
        materialNoList.add(materialNo);
        List<Map<String, Object>> materialByNo = materialService.getMaterialByNo(materialNoList);
        Map<String, Object> materialToMap = changeMaterialToMap(materialByNo);//将查询到的物料信息转成map
        //取出当前物料的信息
        Map<String,Object> currentMaterial = VtuzxUtil.getObject(materialToMap,materialNo);
        //取出入库单明细id，判断托盘是否打印过
        String operNo = VtuzxUtil.getString(map,"operNo");//工序汇报单号(铸造的)

        Tray tray = new Tray();
        String BILLNO =  IXqcConst.createBillNo(BillType.TPTRAY);//托盘号
        tray.setFBILLNO(BILLNO);//托盘号
        tray.setITEMNUMBER(materialNo);//件号
        //判断物料是否启用批号，启用的话默认999
//        int FISBATCHMANAGE = VtuzxUtil.getInt(currentMaterial,"FISBATCHMANAGE");//是否启用批号0未启用，1启用

        tray.setFLOT(flot);//批号
        tray.setSUFFIX(suffix);//后缀
        tray.setFQTY(VtuzxUtil.getDouble(map,"fqty"));//托盘中物料数量
        tray.setFMATERIALNUMBER(materialNo);
        tray.setFMATERIALNAME(VtuzxUtil.getString(currentMaterial,"FNAME"));
        tray.setFUNITID(VtuzxUtil.getString(currentMaterial,"unitNo"));
        tray.setFUNITNAME(VtuzxUtil.getString(currentMaterial,"unitName"));
        tray.setFSPECIFICATION(VtuzxUtil.getString(currentMaterial,"FSPECIFICATION"));
        tray.setISPACKAGE(true);
        tray.setCREATETIME(new Date());
        tray.setCREATEUSERNAME(userName);
        tray.setUPDATETIME(new Date());
        tray.setOPERNOSM(operNo);
        tray.setIRONNO(ironNo);
//        if (!VtuzxUtil.isEmpty(operNo)){
//            tray.setFOPERPNO(operNo);
//        }

        tray.setINSTOCKTIME(DateUtils.strToDate(inStockTime,"yyyy-MM-dd HH:mm:ss"));//入库日期

        boolean b = trayService.saveOrUpdate(tray);
        return BILLNO;
//        }



    }

    /**
     * 机加通过补料的方式创建托盘
     * @param map
     * @param userName
     * @return
     * @throws Exception
     */
    @Override
    public String createTrayPdaByFeed(Map<String, Object> map, String userName) throws Exception {
        String materialNo = VtuzxUtil.getString(map,"itemnumber");//物料编码
        String flot = VtuzxUtil.getString(map,"flot");//批号
        String suffix = VtuzxUtil.getString(map,"suffix");//后缀
        String inStockTime = VtuzxUtil.getString(map,"inStockTime");//入库日期
        //根据编码查询名称等信息
        List<String> materialNoList = new ArrayList<>();
        materialNoList.add(materialNo);
        List<Map<String, Object>> materialByNo = materialService.getMaterialByNo(materialNoList);
        Map<String, Object> materialToMap = changeMaterialToMap(materialByNo);//将查询到的物料信息转成map
        //取出当前物料的信息
        Map<String,Object> currentMaterial = VtuzxUtil.getObject(materialToMap,materialNo);
        //取出入库单明细id，判断托盘是否打印过
        String operNo = VtuzxUtil.getString(map,"operNo");//工序汇报单号(铸造的)

        Tray tray = new Tray();
        String BILLNO =  IXqcConst.createBillNo(BillType.TPTRAY);//托盘号
        tray.setFBILLNO(BILLNO);//托盘号
        tray.setITEMNUMBER(VtuzxUtil.getString(currentMaterial,"FSPECIFICATION"));//件号

        tray.setFLOT(flot);//批号
        tray.setSUFFIX(suffix);//后缀
        tray.setFQTY(VtuzxUtil.getDouble(map,"fqty"));//托盘中物料数量
        tray.setFMATERIALNUMBER(materialNo);
        tray.setFMATERIALNAME(VtuzxUtil.getString(currentMaterial,"FNAME"));
        tray.setFUNITID(VtuzxUtil.getString(currentMaterial,"unitNo"));
        tray.setFUNITNAME(VtuzxUtil.getString(currentMaterial,"unitName"));
        tray.setFSPECIFICATION(VtuzxUtil.getString(currentMaterial,"FSPECIFICATION"));
        tray.setISPACKAGE(true);
        tray.setCREATETIME(new Date());
        tray.setCREATEUSERNAME(userName);
        tray.setUPDATETIME(new Date());
        tray.setOPERNOSM(operNo);
        if (!VtuzxUtil.isEmpty(operNo)){
            tray.setFOPERPNO(operNo);
        }

        tray.setINSTOCKTIME(DateUtils.strToDate(inStockTime,"yyyy-MM-dd HH:mm:ss"));//入库日期

        boolean b = trayService.saveOrUpdate(tray);
        return BILLNO;
    }

    /**
     * 托盘绑定工单号
     * @param trayData
     * @param operpNo
     * @return
     * @throws Exception
     */
    @Override
    public Boolean bandingOperp(Map<String, Object> trayData, String operpNo,String moBillNo) throws Exception {
        String billNo = VtuzxUtil.getString(trayData,"fbillno");
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        tray.setFOPERPNO(operpNo);

        boolean b = trayService.updateById(tray);

        return b;
    }

    /**
     * 获取托盘信息，工序汇报时用
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getTrayPlan(Map<String, Object> map) throws Exception {
        String billNo = map.get("billNo").toString();//托盘信息
        String operBillNo = VtuzxUtil.getString(map,"operBillNo");//工序计划单号
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO,billNo));
        if (null == tray){
            throw new RuntimeException("该托盘信息不存在");
        }
        //工序计划详情
        Map<String,Object> operpData = VtuzxUtil.getObject(map,"operpData");
        String departName = VtuzxUtil.getString(operpData,"departName");
        String operno = VtuzxUtil.getString(operpData,"operNo");//工序号
        //机加车间需要判断这个托盘，是否汇报过这个工序，还需判断这个托盘是否属于这个工单
        if ("机加车间".equals(departName)){
            if (!operBillNo.equals(tray.getFOPERPNO())){
                throw new RuntimeException(String.format("当前托盘不属于此工单,属于%s",tray.getFOPERPNO()));
            }
            if (!VtuzxUtil.isEmpty(tray.getPROCESS())){
                if (tray.getPROCESS().contains(operno)){
                    throw new RuntimeException(String.format("托盘号:%s,已经汇报过工序:%s",billNo,operno));
                }
            }
            //如果是末序的话校验之前的所有序是否都汇报了(1是末序)
            int beginandend = VtuzxUtil.getInt(operpData,"beginandend");
            if(beginandend == 1){
                String process = tray.getPROCESS();//已经汇报过的序

                List<String> unOptList = checkAllPlan(process, operBillNo,billNo);


                //如果返回的集合有值说明有没汇报
                if (!VtuzxUtil.isEmpty(unOptList)){
                    throw new RuntimeException(String.format("存在未汇报完的工序:%s,无法直接汇报末序",unOptList.toString()));
                }


            }
        }
//        else if ("包装车间".equals(departName)){//包装车间需要判断托盘是否在包装检
//            Boolean ispackage = tray.getISPACKAGE();
//            if (!ispackage){
//                throw new RuntimeException("当前托盘不在包装间,请调拨至包间");
//            }
//        }
        //判断当前序有没有汇报过，报过的话，再次汇报的数量不能大于原托数量 - 当前序的完工数量 -之前的废料数量(工废 + 料废)
        //没报过的话不能超过原托数量 - 之前的废料数量(工废 + 料废)
        List<SfcOptrpt> sfcOptrpts = sfcOptrptDao.selectList(new LambdaQueryWrapper<SfcOptrpt>()
                .eq(SfcOptrpt::getTrayNo, billNo)
                .eq(SfcOptrpt::getWorkShopName,"机加车间")
                .eq(SfcOptrpt::getOperpNo, operno));
        if (!VtuzxUtil.isEmpty(sfcOptrpts)){//当前工序报过
            List<String> billNoList = sfcOptrpts.stream()
                    .map(SfcOptrpt::getBillNo)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            List<SfcOptrptDetail> sfcOptrptDetails = sfcOptrptDetailDao.selectList(new LambdaQueryWrapper<SfcOptrptDetail>()
                    .in(SfcOptrptDetail::getBillNo, billNoList));
            double reportCount = sfcOptrptDetails.stream()//当前工序汇报的完工数量总和
                    .mapToDouble(SfcOptrptDetail::getEndQty)
                    .sum();
            Double failCount = sfcOptrptService.getFailCount(Integer.parseInt(operno), billNo);
            tray.setOptCount( tray.getFQTY() - reportCount);
        } else {//如果当前序没有汇报过不能超过原托数量 - 之前的废料数量(工废 + 料废)
            List<SfcOptrpt> sfcOptrptList = sfcOptrptDao.selectList(new LambdaQueryWrapper<SfcOptrpt>()
                    .eq(SfcOptrpt::getTrayNo, billNo)
                    .eq(SfcOptrpt::getWorkShopName,"机加车间"));
            double failCount = 0.0;//之前工序合计的料废数量
            if (!VtuzxUtil.isEmpty(sfcOptrptList)){
                List<String> billNoList = sfcOptrptList.stream()
                        .map(SfcOptrpt::getBillNo)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                //查询汇报明细
                List<SfcOptrptDetail> sfcOptrptDetails = sfcOptrptDetailDao.selectList(new LambdaQueryWrapper<SfcOptrptDetail>()
                        .in(SfcOptrptDetail::getBillNo, billNoList));
                failCount = sfcOptrptDetails.stream()
                        .mapToDouble(d -> d.getProcessFailQty() + d.getMaterialFailQty())
                        .sum();

            }
            tray.setOptCount(tray.getFQTY() - failCount);
        }

        Map<String,Object> data = new HashMap<>();
        data.put("data",tray);
        return data;
    }



    /**
     * 机加车间校验托盘是否所有序都汇报了
     * @return
     */
    private List<String> checkAllPlan(String process,String operBillNo,String trayNo) throws Exception{
        //根据工单号查询所有计划，排除末序
        List<SfcproplanDetail> sfcproplanDetailList = sfcproplanDetailDao.selectList(new LambdaQueryWrapper<SfcproplanDetail>()
                .eq(SfcproplanDetail::getBillNo, operBillNo)
                .ne(SfcproplanDetail::getBeginandend,1));
        List<String> operNoList = new ArrayList<>();//所有工序号集合
        for (SfcproplanDetail sfcproplanDetail : sfcproplanDetailList){
            String operNo = String.valueOf(sfcproplanDetail.getOperNo());
            if (!operBillNo.contains(operNo)){
                operNoList.add(operNo);
            }
        }
        List<String> unOptList = new ArrayList<>();//没有汇报的工序集合
        List<String> failOptList = new ArrayList<>();//没有汇报的工序集合
        for (String operNo : operNoList){//有一个没包含的就说明没汇报
            if (!process.contains(operNo)){
                unOptList.add(operNo);
            }
        }
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, trayNo));
        Double fqty = tray.getFQTY();//托盘数量
        //再次校验判断这些没有记录的工序号,如果这道序的完工数量合计 + 其他序的汇报的废料数量合计 = 托盘数
        //说明这个序也完事了(避免报完序后有那种补报废料的情况)
        if (!VtuzxUtil.isEmpty(unOptList)){
            for (String operNo : unOptList){
                Map<String, Object> map = sfcOptrptService.optrptCount(Integer.parseInt(operNo), trayNo);
                Double failCount = sfcOptrptService.getFailCount(Integer.parseInt(operNo), trayNo);//其他序的废料数量合计
                Double sumEndQty = VtuzxUtil.getDouble(map,"sumEndQty");//这倒序的完工数量合计
                if(failCount + sumEndQty >= fqty){
                    tray.setPROCESS(tray.getPROCESS() + "," + operNo);
                } else {//如果不相等，说明这道序确实没完事
                    failOptList.add(operNo);
                }
            }
            boolean b = trayService.updateById(tray);
        }

        return failOptList;
    }

    /**
     * 托盘绑定已经汇报过的工序号(不是工序单号)
     * @param trayData
     * @param operpData
     * @return
     * @throws Exception
     */
    @Override
    public Boolean bandingProcess(Map<String, Object> trayData, Map<String, Object> operpData, Double count) throws Exception {
        String billNo = VtuzxUtil.getString(trayData,"fbillno");
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        String operNo = VtuzxUtil.getString(operpData,"operNo");
        //修改托盘上的数量为报工的合格数量
//        tray.setFQTY(count);
        //通过逗号拼接，第一次不用拼接
        if (VtuzxUtil.isEmpty(tray.getPROCESS())){
            tray.setPROCESS(operNo);
        } else {
            tray.setPROCESS(tray.getPROCESS() + "," + operNo);
        }

        boolean b = trayService.updateById(tray);

        return b;
    }

    /**
     * 托盘绑定已经汇报过的工单号(包装车间)
     * @param trayData
     * @param operpData
     * @return
     * @throws Exception
     */
    @Override
    public Boolean bandingProcessPackage(Map<String, Object> trayData, Map<String, Object> operpData, SfcOptrptDetail detail,String ERPBIllNo) throws Exception {
        String billNo = VtuzxUtil.getString(trayData,"fbillno");
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        //修改托盘上的数量为原有数量 - 完工数量
        tray.setFQTY(tray.getFQTY() - detail.getEndQty());
        //通过逗号拼接，第一次不用拼接
        if (VtuzxUtil.isEmpty(tray.getPACKAGEPROCESS())){
            tray.setPACKAGEPROCESS(ERPBIllNo);
        } else {
            tray.setPACKAGEPROCESS(tray.getPROCESS() + "," + ERPBIllNo);
        }

        boolean b = trayService.updateById(tray);

        return b;
    }

    /**
     * 修改托盘的仓库和仓位信息
     * @param trayno
     * @param trayStockNo
     * @param trayLocationNo
     */
    @Override
    public void updateTrayLocation(String trayno, String trayStockNo, String trayLocationNo,String instockTime) {
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>().eq(Tray::getFBILLNO, trayno));
        tray.setLOCATIONNO(trayLocationNo);
        tray.setSTOCKNO(trayStockNo);
        tray.setSTOCKNAME("机加成品库");
        tray.setPRODUCTIONDATE(DateUtils.strToDate(instockTime,"yyyy-MM-dd"));
        tray.setFLOT(instockTime.substring(0,10));
        trayDao.updateById(tray);
    }

    /**
     * 获取托盘信息(调拨申请扫码时用)
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getTrayTransfer(Long userId, Map<String, Object> map) throws Exception {
//        Map<String,Object> currentData = VtuzxUtil.getObject(map,"currentData");//当前物料信息
        String billNo = VtuzxUtil.getString(map,"billNo");//扫码后的信息(可能是托号，有可能是仓位)
        //如果是托号的话，物料就不能是包材(返回托盘信息)
        //如果是仓位，返回仓位信息
        if (billNo.startsWith("TPTRAY")){
//            String fmaterialNo = VtuzxUtil.getString(currentData,"fmaterialno");
//            if (fmaterialNo.startsWith("05")){
//                throw new RuntimeException("包材没有托号,请扫描仓位");
//            }
            Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                    .eq(Tray::getFBILLNO,billNo)
                    .eq(Tray::getISPACKAGE,true));
            if (null == tray){
                throw new RuntimeException("该托盘信息不存在,或者已经调拨到包装间");
            }
            if (!VtuzxUtil.isEmpty(tray.getISSOURCE())){
                if(tray.getISSOURCE()){
                    throw new RuntimeException("托码已合并,请扫描合托后的码");
                }
            }
            Map<String,Object> data = new HashMap<>();
            data.put("data",tray);
            data.put("isTray",true);//是否是托盘信息
            return data;
        } else if (billNo.startsWith("IRON")){//合并后的托号
            List<Tray> trayList = trayDao.selectList(new LambdaQueryWrapper<Tray>()
                    .eq(Tray::getIRONNO,billNo)
                    .eq(Tray::getISPACKAGE, true));
            if (null == trayList){
                throw new RuntimeException("托盘信息不存在");
            }
            Map<String,Object> data = new HashMap<>();
            data.put("data",trayList);
            data.put("isTray",false);//是否是托盘信息
            return data;
        } else {
            //扫描仓位的话查询金蝶的库存信息,并返回
            if ("998".equals(billNo) || "A000".equals(billNo)){
                throw new RuntimeException("初始化和A000仓位无法扫描");
            }
            List<VtuzxMap> inventoryByLocation = iVtuzxKingdeeService.getInventoryByLocation(userId, billNo);
//            List<Tray> trayList = trayDao.selectList(new LambdaQueryWrapper<Tray>()
//                    .eq(Tray::getLOCATIONNO,billNo)
//                    .eq(Tray::getISPACKAGE, true));
            if (VtuzxUtil.isEmpty(inventoryByLocation)){
                throw new RuntimeException("仓位上没有托盘信息");
            }
            Map<String,Object> data = new HashMap<>();
            data.put("data",inventoryByLocation);
            data.put("isTray",false);//是否是托盘信息
            return data;
        }

    }

    @Override
    public boolean updatetrayCountByPda(Map<String, Object> map) throws Exception {
        String billNo = VtuzxUtil.getString(map,"fbillno");//托盘号
        Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                .eq(Tray::getFBILLNO, billNo));
        Double count = VtuzxUtil.getDouble(map,"fqty");//托盘号
        String flot = VtuzxUtil.getString(map,"flot");//批号
        String trayFLOT = tray.getFLOT();
        if (!VtuzxUtil.isEmpty(flot) && !flot.equals(trayFLOT)){
            tray.setFLOT(flot);
        }
        tray.setFQTY(count);
        tray.setUPDATETIME(new Date());
        boolean b = trayService.updateById(tray);
        return b;
    }

    /**
     * 获取托盘信息(调拨时用)
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getTrayAllocation(Map<String, Object> map) throws Exception {

        String billNo = VtuzxUtil.getString(map,"billNo");//扫码后的信息(可能是托号，有可能是仓位)
        //如果是托号的话，物料就不能是包材(返回托盘信息)
        //如果是仓位，返回仓位信息
        if (billNo.startsWith("TPTRAY")){
            Tray tray = trayDao.selectOne(new LambdaQueryWrapper<Tray>()
                    .eq(Tray::getFBILLNO,billNo)
                    .eq(Tray::getISPACKAGE,true));
            if (null == tray){
                throw new RuntimeException("该托盘信息不存在,或者已经调拨到包装间");
            }
            if (!VtuzxUtil.isEmpty(tray.getISSOURCE())){
                if(tray.getISSOURCE()){
                    throw new RuntimeException("托码已合并,请扫描合托后的码");
                }
            }
            Map<String,Object> data = new HashMap<>();
            data.put("data",tray);
            data.put("isTray",true);//是否是托盘信息
            return data;
        } else if (billNo.startsWith("IRON")){//合并后的托号
            List<Tray> trayList = trayDao.selectList(new LambdaQueryWrapper<Tray>()
                    .eq(Tray::getIRONNO,billNo)
                    .eq(Tray::getISPACKAGE, true));
            if (null == trayList){
                throw new RuntimeException("托盘信息不存在");
            }
            Map<String,Object> data = new HashMap<>();
            data.put("data",trayList);
            data.put("isTray",false);//是否是托盘信息
            return data;
        } else {
            throw new RuntimeException("托盘信息有误,请确认");
        }

    }

    @Override
    public String createTrayPdaByKu(Map<String, Object> map, String userName) throws Exception {
        String materialNo = VtuzxUtil.getString(map,"itemnumber");//物料编码
        String flot = VtuzxUtil.getString(map,"flot");//批号
        String locationNo = VtuzxUtil.getString(map,"locationNo");//仓位
        String stockNo = VtuzxUtil.getString(map,"stockNo");//仓库
        String produceDate = VtuzxUtil.getString(map,"produceDate");//生产日期
        //限制批号必录
        if (VtuzxUtil.isEmpty(flot)){
            throw new RuntimeException("批号必填");
        }
        if (VtuzxUtil.isEmpty(produceDate)){
            throw new RuntimeException("生产日期必填");
        }

        String suffix = VtuzxUtil.getString(map,"suffix");//后缀
        String inStockTime = VtuzxUtil.getString(map,"inStockTime");//入库日期
        //根据编码查询名称等信息
        List<String> materialNoList = new ArrayList<>();
        materialNoList.add(materialNo);
        List<Map<String, Object>> materialByNo = materialService.getMaterialByNo(materialNoList);
        Map<String, Object> materialToMap = changeMaterialToMap(materialByNo);//将查询到的物料信息转成map
        //取出当前物料的信息
        Map<String,Object> currentMaterial = VtuzxUtil.getObject(materialToMap,materialNo);
        //取出入库单明细id，判断托盘是否打印过
        String operNo = VtuzxUtil.getString(map,"operNo");//工序汇报单号(铸造的)

        Tray tray = new Tray();
        String BILLNO =  IXqcConst.createBillNo(BillType.TPTRAY);//托盘号
        tray.setFBILLNO(BILLNO);//托盘号
        tray.setITEMNUMBER(materialNo);//件号
        //判断物料是否启用批号，启用的话默认999
//        int FISBATCHMANAGE = VtuzxUtil.getInt(currentMaterial,"FISBATCHMANAGE");//是否启用批号0未启用，1启用

        tray.setFLOT(flot);//批号
        tray.setSUFFIX(suffix);//后缀
        tray.setFQTY(VtuzxUtil.getDouble(map,"fqty"));//托盘中物料数量
        tray.setFMATERIALNUMBER(materialNo);
        tray.setFMATERIALNAME(VtuzxUtil.getString(currentMaterial,"FNAME"));
        tray.setFUNITID(VtuzxUtil.getString(currentMaterial,"unitNo"));
        tray.setFUNITNAME(VtuzxUtil.getString(currentMaterial,"unitName"));
        tray.setFSPECIFICATION(VtuzxUtil.getString(currentMaterial,"FSPECIFICATION"));
        tray.setISPACKAGE(true);
        tray.setCREATETIME(new Date());
        tray.setCREATEUSERNAME(userName);
        tray.setUPDATETIME(new Date());
        tray.setOPERNOSM(operNo);
        tray.setLOCATIONNO(locationNo);
        tray.setSTOCKNO(stockNo);
        tray.setPRODUCTIONDATE(DateUtils.strToDate(produceDate,"yyyy-MM-dd'T'HH:mm:ss"));
//        tray.setIRONNO(ironNo);
//        if (!VtuzxUtil.isEmpty(operNo)){
//            tray.setFOPERPNO(operNo);
//        }

        tray.setINSTOCKTIME(DateUtils.strToDate(inStockTime,"yyyy-MM-dd HH:mm:ss"));//入库日期

        boolean b = trayService.saveOrUpdate(tray);
        return BILLNO;
//        }

    }

    /**
     * key;物料编码 val:物料相关信息(map)
     * @param materialList
     * @return
     */
    private Map<String,Object> changeMaterialToMap(List<Map<String,Object>> materialList){
        Map<String,Object> dataMap = new HashMap<>();
        for (Map<String,Object> data : materialList){
            String FNUMBER = VtuzxUtil.getString(data,"FNUMBER");
            String unitNo = VtuzxUtil.getString(data,"unitNo");//单位编码
            String FNAME = VtuzxUtil.getString(data,"FNAME");//物料名称
            String FSPECIFICATION = VtuzxUtil.getString(data,"FSPECIFICATION");//规格
            String unitName = VtuzxUtil.getString(data,"unitName");//规格
            int FISBATCHMANAGE = VtuzxUtil.getInt(data,"FISBATCHMANAGE");//是否启用批号0未启用，1启用
            Map<String,Object> materialMap = new HashMap<>();
            materialMap.put("FNUMBER",FNUMBER);
            materialMap.put("unitNo",unitNo);
            materialMap.put("FNAME",FNAME);
            materialMap.put("FSPECIFICATION",FSPECIFICATION);
            materialMap.put("unitName",unitName);
            materialMap.put("FISBATCHMANAGE",FISBATCHMANAGE);
            dataMap.put(FNUMBER,materialMap);
        }
        return dataMap;
    }

}